package edu.moravian.game;

import edu.moravian.UI.*;
import edu.moravian.entity.Enemy;
import edu.moravian.grid.Grid;
import edu.moravian.managers.*;
import edu.moravian.math.Point2D;
import edu.moravian.player.PlayerInfo;
import edu.moravian.sound.SoundManager;
import edu.moravian.world.World2D;
import edu.moravian.world.WorldDescriptor;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author stejr02
 */
public class TowerDefenseGame implements Game
{

    private static final double TIME_BETWEEN_WAVES = 5.0;
    private static final int PLAY_NUM_CELLS_ACROSS = 20;
    private static final int PLAY_NUM_CELLS_UP_DOWN = 15;
    private static int THEME_LENGTH = 127;
    private static int NEXT_THEME_END_TIME = 0;
    private boolean done;
    private boolean gameOver;
    private GameViewManager gameViewManager;
    private Grid playAreaGrid;
    private WorldDescriptor playAreaWD;
    private PlayerInfo playerInfo;
    private SoundManager soundManager;
    private EnemyManager enemyManager;
    private OrdinanceManager ordinanceManager;
    private TowerManager towerManager;
    private WaveGenerator waveGenerator;
    private double elapsedTime = 0;

    /**
     * Create the game
     *
     * @param worldWidth the width of the world
     * @param worldHeight the height of the world
     */
    public TowerDefenseGame(WorldDescriptor world)
    {
        this.done = false;
        this.gameOver = false;

        double playAreaXMax = world.getMaxX() * .8;

        Point2D upperRightOfPlayArea = new Point2D(playAreaXMax, world.getMaxY());
        playAreaWD = new WorldDescriptor(world.getLowerLeft(), upperRightOfPlayArea);
        playAreaGrid = new Grid(PLAY_NUM_CELLS_ACROSS, PLAY_NUM_CELLS_UP_DOWN, playAreaWD);
        
        enemyManager = new EnemyManager();
        waveGenerator = new WaveGenerator(playAreaWD, playAreaGrid);
        towerManager = new TowerManager();
        ordinanceManager = new OrdinanceManager(playAreaWD);

        playerInfo = new PlayerInfo();
        soundManager = new SoundManager();

        gameViewManager = new GameViewManager(world, ordinanceManager, towerManager, enemyManager, playAreaGrid, playerInfo, playAreaWD, waveGenerator);

    }

    /**
     * Update the game to the next frame
     */
    @Override
    public void update(double delta)
    {
        elapsedTime += delta;

        if (gameOver == false)
        {
            enemyManager.update(delta);
            towerManager.update(delta, ordinanceManager, enemyManager);
            ordinanceManager.update(delta, enemyManager);

            if (elapsedTime > NEXT_THEME_END_TIME)
            {
                soundManager.playTheme();
                NEXT_THEME_END_TIME += THEME_LENGTH;
            }

            if (PlayerInfo.getLivesRemaining() <= 0)
            {
                gameOver = true;
            }
            
            if(waveGenerator.hasNextWave() == false)
            {
                if(enemyManager.getEnemies().iterator().hasNext() == false)
                {
                    gameOver = true;
                }
            }
        }
    }

    /**
     * Draw the current game state
     *
     * @param w2d the graphics to draw to
     */
    @Override
    public void draw(World2D w2d)
    {
        gameViewManager.draw(w2d);
        if (gameOver)
        {
            
            
            w2d.setColor(Color.WHITE);
            int fontSize = 200;
            Font oldFont = w2d.getFont();
            Font newFont = new Font(oldFont.getName(), oldFont.getStyle(), fontSize);
            w2d.setFont(newFont);
        
            if(PlayerInfo.getLivesRemaining() <=0)
            {
                w2d.drawMiddleCenteredString("GAME OVER!", playAreaWD.getCenter());
            }
            else
            {
                w2d.drawMiddleCenteredString("YOU WIN!", playAreaWD.getCenter());
            }
            w2d.setFont(oldFont);
        }
    }

    /**
     * Determine whether the game is done.
     *
     * @return whether the player wanted the game to end
     */
    @Override
    public boolean done()
    {
        return done;
    }

    /**
     * Handle for key presses to control the players motion.
     *
     * @param e the key event
     */
    @Override
    public void handleKeyPress(KeyEvent e)
    {
    }

    /**
     * Handle for key release to control the players motion.
     *
     * @param e the key event
     */
    @Override
    public void handleKeyRelease(KeyEvent e)
    {
    }

    /**
     * A handler method for key events
     *
     * @param e
     */
    @Override
    public void handleKeyTyped(KeyEvent e)
    {
        //'q' is the character to quit at anypoint in the game
        if (e.getKeyChar() == 'q')
        {
            done = true;
            soundManager.stopTheme();
        }

        if (e.getKeyChar() == 's')
        {
            if(waveGenerator.hasNextWave())
            {
                PlayerInfo.setWave(PlayerInfo.getWave()+1);
                new Thread(new EnemySendThread(waveGenerator, enemyManager)).start();
            }
            
        }
    }

    /**
     * Mouse movement handler
     *
     * @param location
     */
    @Override
    public void handleMouseMoved(Point2D location)
    {
        if(gameOver == false)
        {
            gameViewManager.handleMouseMoved(location);
        }
    }

    /**
     * Mouse click handler
     *
     * @param location
     */
    @Override
    public void handleMouseClicked(Point2D location)
    {
        if(gameOver == false)
        {
            gameViewManager.handleMouseClick(location);
        }
    }
    
   

}
